package main

import (
    "database/sql"
    "encoding/json"
    "log"
    "net/http"
    "os"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/cors"
    "github.com/go-redis/redis/v8"
    _ "github.com/mattn/go-sqlite3"
)

// Place 结构体定义
type Place struct {
    ID          int64       `json:"id"`
    Name        string      `json:"name"`
    Category    string      `json:"category"`
    Longitude   float64     `json:"longitude"`
    Latitude    float64     `json:"latitude"`
    Description string      `json:"description"`
    Attributes  []Attribute `json:"attributes"`
    CreatedAt   time.Time   `json:"created_at"`
}

// Attribute 结构体定义
type Attribute struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

// 响应结构体
type Response struct {
    Status  string      `json:"status"`
    Message string      `json:"message,omitempty"`
    Data    interface{} `json:"data,omitempty"`
}

var (
    db    *sql.DB
    cache *redis.Client
)

func init() {
    // 初始化数据库
    var err error
    db, err = sql.Open("sqlite3", "places.db")
    if err != nil {
        log.Fatal(err)
    }

    // 创建表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS places (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            category TEXT,
            longitude REAL NOT NULL,
            latitude REAL NOT NULL,
            description TEXT,
            attributes TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    `)
    if err != nil {
        log.Fatal(err)
    }

    // 初始化Redis缓存
    cache = redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "",
        DB:       0,
    })
}

func main() {
    router := gin.Default()

    // CORS中间件
    config := cors.DefaultConfig()
    config.AllowAllOrigins = true
    router.Use(cors.New(config))

    // 路由定义
    api := router.Group("/api")
    {
        places := api.Group("/places")
        {
            places.GET("", getPlaces)
            places.POST("", createPlace)
            places.GET("/:id", getPlace)
            places.PUT("/:id", updatePlace)
            places.DELETE("/:id", deletePlace)
            places.POST("/import", importPlaces)
            places.GET("/export", exportPlaces)
            places.GET("/search", searchPlaces)
        }
    }

    router.Run(":8080")
}

// 获取所有地点
func getPlaces(c *gin.Context) {
    // 尝试从缓存获取
    cacheKey := "places:all"
    if cached, err := cache.Get(c, cacheKey).Result(); err == nil {
        var places []Place
        if err := json.Unmarshal([]byte(cached), &places); err == nil {
            c.JSON(http.StatusOK, Response{
                Status: "success",
                Data:   places,
            })
            return
        }
    }

    // 从数据库获取
    rows, err := db.Query("SELECT * FROM places")
    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }
    defer rows.Close()

    var places []Place
    for rows.Next() {
        var p Place
        var attributesJSON string
        err := rows.Scan(&p.ID, &p.Name, &p.Category, &p.Longitude, &p.Latitude,
            &p.Description, &attributesJSON, &p.CreatedAt)
        if err != nil {
            continue
        }
        json.Unmarshal([]byte(attributesJSON), &p.Attributes)
        places = append(places, p)
    }

    // 更新缓存
    if placesJSON, err := json.Marshal(places); err == nil {
        cache.Set(c, cacheKey, placesJSON, time.Minute*5)
    }

    c.JSON(http.StatusOK, Response{
        Status: "success",
        Data:   places,
    })
}

// 创建地点
func createPlace(c *gin.Context) {
    var place Place
    if err := c.ShouldBindJSON(&place); err != nil {
        c.JSON(http.StatusBadRequest, Response{
            Status:  "error",
            Message: "无效的请求数据",
        })
        return
    }

    attributesJSON, _ := json.Marshal(place.Attributes)
    result, err := db.Exec(`
        INSERT INTO places (name, category, longitude, latitude, description, attributes)
        VALUES (?, ?, ?, ?, ?, ?)
    `, place.Name, place.Category, place.Longitude, place.Latitude,
        place.Description, string(attributesJSON))

    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }

    id, _ := result.LastInsertId()
    place.ID = id

    // 清除缓存
    cache.Del(c, "places:all")

    c.JSON(http.StatusOK, Response{
        Status: "success",
        Data:   place,
    })
}

// 获取单个地点
func getPlace(c *gin.Context) {
    id := c.Param("id")
    
    // 尝试从缓存获取
    cacheKey := "places:" + id
    if cached, err := cache.Get(c, cacheKey).Result(); err == nil {
        var place Place
        if err := json.Unmarshal([]byte(cached), &place); err == nil {
            c.JSON(http.StatusOK, Response{
                Status: "success",
                Data:   place,
            })
            return
        }
    }

    var place Place
    var attributesJSON string
    err := db.QueryRow("SELECT * FROM places WHERE id = ?", id).
        Scan(&place.ID, &place.Name, &place.Category, &place.Longitude,
            &place.Latitude, &place.Description, &attributesJSON, &place.CreatedAt)

    if err == sql.ErrNoRows {
        c.JSON(http.StatusNotFound, Response{
            Status:  "error",
            Message: "地点不存在",
        })
        return
    }

    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }

    json.Unmarshal([]byte(attributesJSON), &place.Attributes)

    // 更新缓存
    if placeJSON, err := json.Marshal(place); err == nil {
        cache.Set(c, cacheKey, placeJSON, time.Minute*5)
    }

    c.JSON(http.StatusOK, Response{
        Status: "success",
        Data:   place,
    })
}

// 更新地点
func updatePlace(c *gin.Context) {
    id := c.Param("id")
    var place Place
    if err := c.ShouldBindJSON(&place); err != nil {
        c.JSON(http.StatusBadRequest, Response{
            Status:  "error",
            Message: "无效的请求数据",
        })
        return
    }

    attributesJSON, _ := json.Marshal(place.Attributes)
    result, err := db.Exec(`
        UPDATE places 
        SET name = ?, category = ?, longitude = ?, latitude = ?, 
            description = ?, attributes = ?
        WHERE id = ?
    `, place.Name, place.Category, place.Longitude, place.Latitude,
        place.Description, string(attributesJSON), id)

    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }

    affected, _ := result.RowsAffected()
    if affected == 0 {
        c.JSON(http.StatusNotFound, Response{
            Status:  "error",
            Message: "地点不存在",
        })
        return
    }

    // 清除缓存
    cache.Del(c, "places:all", "places:"+id)

    c.JSON(http.StatusOK, Response{
        Status: "success",
        Data:   place,
    })
}

// 删除地点
func deletePlace(c *gin.Context) {
    id := c.Param("id")
    result, err := db.Exec("DELETE FROM places WHERE id = ?", id)
    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }

    affected, _ := result.RowsAffected()
    if affected == 0 {
        c.JSON(http.StatusNotFound, Response{
            Status:  "error",
            Message: "地点不存在",
        })
        return
    }

    // 清除缓存
    cache.Del(c, "places:all", "places:"+id)

    c.JSON(http.StatusOK, Response{
        Status: "success",
    })
}

// 导入地点
func importPlaces(c *gin.Context) {
    file, err := c.FormFile("file")
    if err != nil {
        c.JSON(http.StatusBadRequest, Response{
            Status:  "error",
            Message: "没有上传文件",
        })
        return
    }

    src, err := file.Open()
    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }
    defer src.Close()

    var places []Place
    if err := json.NewDecoder(src).Decode(&places); err != nil {
        c.JSON(http.StatusBadRequest, Response{
            Status:  "error",
            Message: "无效的JSON格式",
        })
        return
    }

    tx, err := db.Begin()
    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }

    for _, place := range places {
        attributesJSON, _ := json.Marshal(place.Attributes)
        _, err := tx.Exec(`
            INSERT INTO places (name, category, longitude, latitude, description, attributes)
            VALUES (?, ?, ?, ?, ?, ?)
        `, place.Name, place.Category, place.Longitude, place.Latitude,
            place.Description, string(attributesJSON))

        if err != nil {
            tx.Rollback()
            c.JSON(http.StatusInternalServerError, Response{
                Status:  "error",
                Message: err.Error(),
            })
            return
        }
    }

    if err := tx.Commit(); err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }

    // 清除缓存
    cache.Del(c, "places:all")

    c.JSON(http.StatusOK, Response{
        Status: "success",
    })
}

// 导出地点
func exportPlaces(c *gin.Context) {
    rows, err := db.Query("SELECT * FROM places")
    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }
    defer rows.Close()

    var places []Place
    for rows.Next() {
        var p Place
        var attributesJSON string
        err := rows.Scan(&p.ID, &p.Name, &p.Category, &p.Longitude, &p.Latitude,
            &p.Description, &attributesJSON, &p.CreatedAt)
        if err != nil {
            continue
        }
        json.Unmarshal([]byte(attributesJSON), &p.Attributes)
        places = append(places, p)
    }

    c.JSON(http.StatusOK, places)
}

// 搜索地点
func searchPlaces(c *gin.Context) {
    keyword := c.Query("keyword")
    category := c.Query("category")

    query := "SELECT * FROM places WHERE 1=1"
    var params []interface{}

    if keyword != "" {
        query += " AND (name LIKE ? OR description LIKE ?)"
        params = append(params, "%"+keyword+"%", "%"+keyword+"%")
    }

    if category != "" {
        query += " AND category = ?"
        params = append(params, category)
    }

    rows, err := db.Query(query, params...)
    if err != nil {
        c.JSON(http.StatusInternalServerError, Response{
            Status:  "error",
            Message: err.Error(),
        })
        return
    }
    defer rows.Close()

    var places []Place
    for rows.Next() {
        var p Place
        var attributesJSON string
        err := rows.Scan(&p.ID, &p.Name, &p.Category, &p.Longitude, &p.Latitude,
            &p.Description, &attributesJSON, &p.CreatedAt)
        if err != nil {
            continue
        }
        json.Unmarshal([]byte(attributesJSON), &p.Attributes)
        places = append(places, p)
    }

    c.JSON(http.StatusOK, Response{
        Status: "success",
        Data:   places,
    })
} 